package org.eclipse.epsilon.emc.jdt;

import org.eclipse.epsilon.emc.jdt.properties.CompilationUnitProperties;
import org.eclipse.epsilon.emc.jdt.properties.EnumDecProperties;
import org.eclipse.epsilon.emc.jdt.properties.JavaProjectProperties;
import org.eclipse.epsilon.emc.jdt.properties.PackageProperties;
import org.eclipse.epsilon.emc.jdt.properties.SingleVariableDecProperties;
import org.eclipse.epsilon.emc.jdt.properties.Properties;
import org.eclipse.epsilon.emc.jdt.properties.TypeDecProperties;
import org.eclipse.epsilon.emc.jdt.properties.VariableDecFragProperties;
import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
import org.eclipse.epsilon.eol.execute.introspection.AbstractPropertyGetter;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.EnumDeclaration;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;

/**
 * This class retrieves the value of properties of JDT model element
 * 
 * @author Cheng Yun
 * 
 */
public class JdtPropertyGetter extends AbstractPropertyGetter {
	@Override
	public Object invoke(Object object, String property)
			throws EolRuntimeException {

		if (object instanceof IJavaProject) {// JavaProjact
			return JavaProjectProperties.getProperty(property).run(object);
		}

		if (object instanceof IPackageFragment) {// Package
			return PackageProperties.getProperty(property).run(object);
		}
		
		if (object instanceof ASTNode) {//ASTNode
			ASTNode node = (ASTNode) object;
			if (property.equals("parent")) {// ASTNode.parent
				return node.getParent();
			}

			if (property.equals("type")) {// ASTNode.type
				return ASTNode.nodeClassForType(node.getNodeType());
			}
		}
		
		if (object instanceof CompilationUnit){// JavaFile
			return CompilationUnitProperties.getProperty(property).run(object);
		}

		if (object instanceof TypeDeclaration) {// Class
			return TypeDecProperties.getProperty(property).run(object);
		}
		
		if (object instanceof EnumDeclaration) {// Enumeration
			return EnumDecProperties.getProperty(property).run(object);
		}

		if (object instanceof FieldDeclaration) {// Field
			FieldDeclaration field = (FieldDeclaration) object;
			return Properties.getProperty(property).run(field);
		}

		if (object instanceof MethodDeclaration) {// Method
			MethodDeclaration method = (MethodDeclaration) object;
			return Properties.getProperty(property).run(method);
		}
		
		if (object instanceof VariableDeclaration){// VariableDeclaration
			if (object instanceof SingleVariableDeclaration) {
				return SingleVariableDecProperties.getProperty(property).run(object);
			}
			
			if (object instanceof VariableDeclarationFragment) {
				return VariableDecFragProperties.getProperty(property).run(object);
			}
		}
		//Statement or Expression
		if ((object instanceof Statement) || (object instanceof Expression)) {
			ASTNode node = (ASTNode) object;
			return Properties.getProperty(property).run(node);
		}
		return null;
	}
}
